#include <iostream>
#include <string>
#include <fstream>
#include <random>

#include "cpp-httplib/httplib.h"

#include "add_contacts.pb.h"

#include "contacts_exception.h"

// cpp-httplib test
// int main()
// {
//     httplib::Server svr;

//     svr.Post("/test-post", [](const httplib::Request& req, httplib::Response& resp)
//     {
//         std::cout << "收到post请求" << std::endl;
//         resp.status = 200;
//     });

//     svr.Get("/test-get", [](const httplib::Request& req, httplib::Response& resp)
//     {
//         std::cout << "接收到get请求" << std::endl;
//         resp.status = 200;
//     });

//     svr.listen("0.0.0.0", 8081);

//     return 0;
// }

const std::string path = "./contacts.bin";

void PrintContacts(const add_contacts::AddContactsRequest& req)
{
    std::cout << "联系人姓名: " << req.name() << std::endl;
    std::cout << "联系人年龄: " << req.age() << std::endl;
    for (size_t j = 0; j < req.phone_size(); ++j)
    {
        const add_contacts::AddContactsRequest_Phone& phone = req.phone(j);
        std::cout << "联系人电话: " << phone.number() << ' ';
        std::cout << "电话类型: " << add_contacts::AddContactsRequest_Phone::PhoneType_Name(phone.type()) << std::endl;
    }
    
    // 写入文件中
    std::ofstream fout(path.c_str(), std::ofstream::out | std::ofstream::trunc | std::ofstream::binary);
    if (!fout.is_open())
        std::cout << path << " open err" << std::endl;
    req.SerializeToOstream(&fout);
    fout.close();
}

static unsigned int random_char()
{
    // 用于随机数引擎获得随机种子
    std::random_device rd;
    // mt19937是c++11的新特性,一种随机数算法,用法与rand()相似,mt19937速度快,周期长
    // 生成伪随机数
    std::mt19937 gen(rd());
    // 随机生成一个整数i,范围[0, 255]
    std::uniform_int_distribution<> dis(0, 255);
    return dis(gen);
}
// 生成UUID(通用唯一标识符)
static std::string generate_hex(const unsigned int len)
{
    std::stringstream ss;
    // 生成len个16进制随机数,将其拼接而成
    for (auto i = 0; i < len; ++i)
    {
        const auto rc = random_char();
        std::stringstream hexstream;
        hexstream << std::hex << rc;
        auto hex = hexstream.str();
        ss << (hex.length() < 2 ? '0' + hex : hex);
    }
    return ss.str();
}

int main()
{
    httplib::Server svr;
    svr.Post("/contacts/add", [](const httplib::Request& req, httplib::Response& resp)
    {
        std::cout << "收到post请求" << std::endl;
        
        add_contacts::AddContactsRequest request;
        add_contacts::AddContactsResponse response;
        try
        {
            if (!request.ParseFromString(req.body))
                throw ContactsException("add contacts parse err");

            PrintContacts(request);
            
            // 设置添加联系人请求
            response.set_success(true);
            response.set_uid(generate_hex(10));

            std::string response_str;
            if (!response.SerializeToString(&response_str))
                throw ContactsException("add contacts serialize err");
            
            // 设置http响应
            resp.body = response_str;
            resp.set_header("Content-Type", "application/protobuf");
            resp.status = 200;
        }
        catch (const ContactsException& e)
        {
            resp.status = 500;
            response.set_success(false);
            response.set_errstring(e.what());
            std::string response_str;
            if (response.SerializeToString(&response_str))
            {
                resp.body = response_str;
                resp.set_header("Content-Type", "application/protobuf");
            }
            std::cout << "/contacts add exception, errstring: " << e.what() << std::endl;
        }
    });

    svr.listen("0.0.0.0", 8081);

    return 0;
}